package com.bosssoft.cloud.wechat.infrastructure.processor;

import com.bosssoft.cloud.wechat.common.infra.config.EipsControllerHandler;
import com.bosssoft.cloud.wechat.core.infra.config.WxControllerHandler;
import org.springframework.boot.autoconfigure.web.WebMvcRegistrations;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.util.CollectionUtils;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import javax.annotation.Resource;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;

/**
 * 配置使用自定义url处理器
 *
 * @author wcy create on 2021/6/24 17:07 下午
 */
@Configuration
@Order(Ordered.HIGHEST_PRECEDENCE)
public class GlobalRegistrationConfiguration implements WebMvcRegistrations {
    /**
     * 重写RequestMapping注解映射处理器，实现自定义处理url
     * 主要用来加url前缀，方便管理
     * 注：
     * spring对于url和method映射关系的处理是在RequestMappingHandlerMapping中实现的。
     * 关联控制器和方法之间的url是在getMappingForMethod方法中完成的。
     * 重写RequestMappingHandlerMapping的getMappingForMethod方法，完成追加url前缀的功能。
     */
    @Override
    public RequestMappingHandlerMapping getRequestMappingHandlerMapping() {
        return new RequestMappingHandlerMapping() {
            @Resource
            private ApplicationContext applicationContext;
            // url控制器
            protected Set<BaseControllerHandler> wxControllerHandlers;
            // 当前是否拥有自定义url前缀的控制器
            protected boolean hasWxControllerHandler = false;

            @Override
            public void afterPropertiesSet() {
                // 初始化url控制器集合
                initWxControllerHandler();
                super.afterPropertiesSet();
            }

            /**
             * 关联控制器和方法之间的url
             *
             * @param method      方法
             * @param handlerType type
             * @return 关联信息mappinginfo
             */
            @Override
            protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
                RequestMappingInfo info = super.getMappingForMethod(method, handlerType);
                if (hasWxControllerHandler && info != null) {
                    for (BaseControllerHandler handler : wxControllerHandlers) {
                        if (handler.isPattern(handlerType)) {
                            return handler.combineRequestMappingInfo(info);
                        }
                    }
                }
                return info;
            }

            /**
             * 初始化url控制器集合
             */
            protected void initWxControllerHandler() {
                wxControllerHandlers = new HashSet<>();
                wxControllerHandlers.addAll(applicationContext.getBeansOfType(WxControllerHandler.class).values());
                wxControllerHandlers.addAll(applicationContext.getBeansOfType(EipsControllerHandler.class).values());
                hasWxControllerHandler = !CollectionUtils.isEmpty(wxControllerHandlers);
            }
        };
    }

    @Override
    public RequestMappingHandlerAdapter getRequestMappingHandlerAdapter() {
        return null;
    }

    @Override
    public ExceptionHandlerExceptionResolver getExceptionHandlerExceptionResolver() {
        return null;
    }
}
